/* 
 * File:   main.c
 * Author: marco
 *
 * Created on 8 de Novembro de 2013, 14:39
 */
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <strings.h>

struct somadores {
    int sumDataTransfer;
    int sumUncondJump;
    int sumCondJump;
    int sumArithmetic;
    int sumAddressModify;
};

struct somadores s;

void inicializaSimulador();
void printRegs();

void inicializaSimulador() {
    inicializaUC();
    inicializaULA();
    s.sumDataTransfer = 0;
    s.sumUncondJump = 0;
    s.sumCondJump = 0;
    s.sumArithmetic = 0;
    s.sumAddressModify = 0;    
}

/*
 * Default:
 * argc = 1
 * argv[0] =  Nome do Programa
 */
int main(int argc, char** argv) {
    char * filename = NULL;
    int passoAPassoFlag = 0;
    int c;
    int maxMem = 256;
    int startIndex = 1;
    int startIndexPrint = 1;
    int endIndexPrint = 255;
    opterr = 0;

    while ((c = getopt(argc, argv, "i:f:m:n:ps:")) != -1)
        switch (c) {
            case 'i':
                startIndexPrint = atoi(optarg);
                break;
            case 'f':
                endIndexPrint = atoi(optarg);
                break;
            case 'm':
                maxMem = atoi(optarg);
                break;
            case 'n':
                filename = optarg;
                break;
            case 'p':
                passoAPassoFlag = 1;
                break;
            case 's':
                startIndex = atoi(optarg);
                break;
            case '?':
                switch (optopt) {
                    case 'i':
                    case 'f':
                    case 'm':
                    case 'n':
                    case 's':
                        fprintf(stderr, "Opção -%c necessita um argumento.\n", optopt);
                        break;
                    default:
                        if (isprint(optopt))
                            fprintf(stderr, "Opção desconhecida `-%c'.\n", optopt);
                        else
                            fprintf(stderr, "Caractere de opção desconhecido `\\x%x'.\n", optopt);
                        abort();
                }
        }

    if (filename == NULL) {
        fprintf(stderr, "Erro nome do arquivo HEX não especificado!\n");
        abort();
    }
    FILE * hex = fopen(filename, "r");
    if (!hex) {
        fprintf(stderr, "Erro ao abrir o arquivo %s!\n", filename);
        abort();
    }

    inicializaMem(startIndexPrint, endIndexPrint, maxMem);

    if (loadProgram(hex, startIndex)) {
        fprintf(stderr, "Erro ao carregar o %s para a memória!\n", filename);
        abort();
    }

    inicializaSimulador();

    do {
        busca();
        if (passoAPassoFlag) {
            printf("Precione 'r' para imprimir os registradores e seguir um passo na execução,\n"
                    "'c' para continuar a execução sem o passo a passo,\n"
                    "ou qualquer outra tecla para seguir um passo na execução: ");            
            char * str = malloc(2);
            scanf("%s", str);
            if (strcmp(str, "r")==0)
                printRegs();
            else if (strcmp(str, "c") == 0)
                passoAPassoFlag = 0;
            printf("\n");
        }
        executa();
    } while (1);
    return EXIT_SUCCESS;
}

void printRegs() {
    printUlaRegs();
    printUcRegs();
}

